#include "stdafx.h"

//#include <atlbase.h>
#include <oledbdm.h>

#include "DMAttributeSet.h"
#include "DMAlgorithmPersistence.h"
using namespace PluginAlgorithms;


System::UInt32	PersistenceReader::Version::get()
{
	USES_ERROR_HANDLING;
	ULONG ulVer = 0L;
	THROW_ON_FAILURE(m_wpRdr->GetVersion(&ulVer)); 

	return (System::UInt32)ulVer;
}
PersistItemTag	PersistenceReader::Tag::get()
{
	USES_ERROR_HANDLING;

	DM_PERSIST_ITEM	tag = 0;
	THROW_ON_FAILURE(m_wpRdr->GetTag(&tag)); 

	return E2PTag(tag);
}

void	PersistenceReader::ReadCollection(System::UInt32* count)
{
	USES_ERROR_HANDLING;
	ULONG ulCount = 0L;
	THROW_ON_FAILURE(m_wpRdr->ReadCollection(&ulCount)); 

	*count	=	(System::UInt32)ulCount;
}

void	PersistenceReader::ReadScope()
{
	USES_ERROR_HANDLING;
	THROW_ON_FAILURE(m_wpRdr->ReadScope()); 

}

void	PersistenceReader::CloseScope()
{
	USES_ERROR_HANDLING;
	THROW_ON_FAILURE(m_wpRdr->CloseScope()); 
}

void	PersistenceReader::OpenScope(PersistItemTag tag)
{
	USES_ERROR_HANDLING;
	THROW_ON_FAILURE(m_wpRdr->OpenScope(P2ETag(tag))); 
}

void	PersistenceReader::StartCollection(PersistItemTag tag, System::UInt32^% count)
{
	USES_ERROR_HANDLING;
	ULONG ulCount = 0L;
	THROW_ON_FAILURE(m_wpRdr->StartCollection(P2ETag(tag), &ulCount)); 
	*count = (System::UInt32)ulCount;
}

void	PersistenceReader::EndCollection()
{
	USES_ERROR_HANDLING;
	THROW_ON_FAILURE(m_wpRdr->EndCollection()); 
}

void	PersistenceReader::GetValue(System::Boolean% val)
{
	USES_ERROR_HANDLING;
	BOOL	fVal = false;
	THROW_ON_FAILURE(m_wpRdr->GetBool(&fVal)); 
	val = fVal ? true : false;
}
void	PersistenceReader::GetValue(System::Double%  val)
{
	USES_ERROR_HANDLING;
	DOUBLE tmpval = 0.0;
	THROW_ON_FAILURE(m_wpRdr->GetDouble(&tmpval)); 
	val = (System::Double)tmpval;
}
void	PersistenceReader::GetValue(System::Int16%  val)
{
	USES_ERROR_HANDLING;
	short tmpval = 0;
	THROW_ON_FAILURE(m_wpRdr->GetShort(&tmpval)); 
	val = (System::Int16)tmpval;
}
void	PersistenceReader::GetValue(System::Int32%  val)
{
	USES_ERROR_HANDLING;
	long tmpval = 0;
	THROW_ON_FAILURE(m_wpRdr->GetLong(&tmpval)); 
	val = (System::Int32)tmpval;
}
void	PersistenceReader::GetValue(System::UInt32%  val)
{
	USES_ERROR_HANDLING;
	ULONG tmpval = 0;
	THROW_ON_FAILURE(m_wpRdr->GetULong(&tmpval)); 
	val = (System::UInt32)tmpval;
}

void	PersistenceReader::GetValue(System::String  ^%   val)
{
	AutoUseContext	apEC;
	USES_ERROR_HANDLING;

	if( (IDMContextServices*)apEC == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	CComPtr<IDMStringHandler> spStringHandler;
	DMString*	pStr = NULL;
	THROW_ON_FAILURE(apEC->GetStringHandler(&spStringHandler));
	THROW_ON_FAILURE(spStringHandler->CreateNewStringHandle(&pStr));


	// Get the string from the reader
	try
	{
		THROW_ON_FAILURE( m_wpRdr->GetString( pStr ) );


		// Get the wchar_t for the string
		const wchar_t*	wszBuff = NULL;
		UINT		uLength = 0;
		THROW_ON_FAILURE( spStringHandler->GetConstStringFromHandle( pStr, &wszBuff, &uLength) );


		val	=	gcnew System::String( wszBuff, 0, uLength );
	}
	// no catch, rethrow the exception
	finally
	{
		if( spStringHandler && pStr )
		{
			spStringHandler->DestroyStringHandle( pStr );
		}
	}
}

/*void	PersistenceReader::GetValue(System::Object __gc ^%*  val)
{
	AutoUseContext	apEC;
	USES_ERROR_HANDLING;

	VARIANT varTmp;
	::VariantInit(&varTmp);


	if( (IDMContextServices*)apEC == NULL )
	{
		throw new System::Exception( new System::String(L"This method should be called from within the LoadContent call") );
	}

	CComPtr<IDMVariantPtrHandler> spVarHandler;
	DMVariantPtr	pVar = NULL;
	THROW_ON_FAILURE(apEC->GetVariantHandler(&spVarHandler));
	THROW_ON_FAILURE(spVarHandler->CreateNewVariantHandle(&pVar));


	// Get the string from the reader
	CURRENT_STATUS =	m_wpRdr->GetVariant(apEC,  pVar );
	if( FAILED(CURRENT_STATUS) ) goto error;


	CURRENT_STATUS = spVarHandler->CopyHandleToVariant( pVar, &varTmp);
	if( FAILED(CURRENT_STATUS) ) goto error;

	*val	=	System::Runtime::InteropServices::Marshal::GetObjectForNativeVariant( (System::IntPtr)(INT_PTR)&varTmp );

error:
	if( spVarHandler && pVar )
	{
		spVarHandler->DestroyVariantHandle( pVar );
	}
	::VariantClear(&varTmp);
	THROW_ON_FAILURE(CURRENT_STATUS);
}
*/
void	PersistenceReader::GetValue(System::DateTime%  val)
{
	USES_ERROR_HANDLING;
	double tmpval = 0;
	THROW_ON_FAILURE(m_wpRdr->GetDate(&tmpval)); 
	val	=	System::DateTime::FromBinary(*(__int64*)&tmpval);
}

void	PersistenceReader::GetAttribute( PersistItemTag tag, System::Boolean% val)
{
	USES_ERROR_HANDLING;
	BOOL	fVal = false;
	THROW_ON_FAILURE(m_wpRdr->GetBoolAttribute(P2ETag(tag), &fVal)); 
	val = fVal ? true : false;
}
void	PersistenceReader::GetAttribute( PersistItemTag tag, System::Double%  val)
{
	USES_ERROR_HANDLING;
	DOUBLE tmpval;
	THROW_ON_FAILURE(m_wpRdr->GetDoubleAttribute(P2ETag(tag), &tmpval)); 
	val = (System::Double)tmpval;
}
void	PersistenceReader::GetAttribute( PersistItemTag tag, System::Int16%  val)
{
	USES_ERROR_HANDLING;
	short tmpval;
	THROW_ON_FAILURE(m_wpRdr->GetShortAttribute(P2ETag(tag), &tmpval)); 
	val = (System::Int16)tmpval;
}
void	PersistenceReader::GetAttribute( PersistItemTag tag, System::Int32%  val)
{
	USES_ERROR_HANDLING;
	long tmpval;
	THROW_ON_FAILURE(m_wpRdr->GetLongAttribute(P2ETag(tag), &tmpval)); 
	val = (System::Int32)tmpval;
}
void	PersistenceReader::GetAttribute( PersistItemTag tag, System::UInt32%  val)
{
	USES_ERROR_HANDLING;
	ULONG tmpval;
	THROW_ON_FAILURE(m_wpRdr->GetULongAttribute(P2ETag(tag), &tmpval)); 
	val = (System::UInt32)tmpval;
}
void	PersistenceReader::GetAttribute( PersistItemTag tag, System::String  ^%   val)
{
	AutoUseContext	apEC;
	USES_ERROR_HANDLING;

	if( (IDMContextServices*)apEC == NULL )
	{
		throw gcnew System::InvalidOperationException();
	}

	CComPtr<IDMStringHandler> spStringHandler;
	DMString*	pStr = NULL;
	THROW_ON_FAILURE(apEC->GetStringHandler(&spStringHandler));
	THROW_ON_FAILURE(spStringHandler->CreateNewStringHandle(&pStr));


	// Get the string from the reader
	try
	{
		THROW_ON_FAILURE( m_wpRdr->GetStringAttribute( P2ETag(tag), pStr ) );

		// Get the wchar_t for the string
		const wchar_t*	wszBuff = NULL;
		UINT		uLength = 0;
		THROW_ON_FAILURE( spStringHandler->GetConstStringFromHandle( pStr, &wszBuff, &uLength) );


		val	=	gcnew System::String( wszBuff, 0, uLength );
	}
	finally
	{
		if( spStringHandler && pStr )
		{
			spStringHandler->DestroyStringHandle( pStr );
		}
	}
}

/*void	PersistenceReader::GetAttribute( PersistItemTag tag, System::Object __gc **  val)
{
	AutoUseContext	apEC;
	USES_ERROR_HANDLING;

	VARIANT varTmp;
	::VariantInit(&varTmp);


	if( (IDMContextServices*)apEC == NULL )
	{
		throw new System::Exception( new System::String(L"This method should be called from within the LoadContent call") );
	}

	CComPtr<IDMVariantPtrHandler> spVarHandler;
	DMVariantPtr	pVar = NULL;
	THROW_ON_FAILURE(apEC->GetVariantHandler(&spVarHandler));
	THROW_ON_FAILURE(spVarHandler->CreateNewVariantHandle(&pVar));


	// Get the string from the reader
	CURRENT_STATUS =	m_wpRdr->GetVariantAttribute(P2ETag(tag), apEC,  pVar );
	if( FAILED(CURRENT_STATUS) ) goto error;


	CURRENT_STATUS = spVarHandler->CopyHandleToVariant( pVar, &varTmp);
	if( FAILED(CURRENT_STATUS) ) goto error;

	*val	=	System::Runtime::InteropServices::Marshal::GetObjectForNativeVariant( (System::IntPtr)(INT_PTR)&varTmp );

error:
	if( spVarHandler && pVar )
	{
		spVarHandler->DestroyVariantHandle( pVar );
	}
	::VariantClear(&varTmp);
	THROW_ON_FAILURE(CURRENT_STATUS);
}*/

void	PersistenceReader::GetAttribute( PersistItemTag tag, System::DateTime %  val)
{
	USES_ERROR_HANDLING;
	double tmpval = 0;
	THROW_ON_FAILURE(m_wpRdr->GetDateAttribute(P2ETag(tag), &tmpval)); 
	val	=	System::DateTime::FromBinary(*(__int64*)&tmpval);
}






void	PersistenceWriter::OpenScope(PersistItemTag tag)
{
	USES_ERROR_HANDLING;
	THROW_ON_FAILURE(m_wpWriter->OpenScope(P2ETag(tag))); 
}

void	PersistenceWriter::CloseScope()
{
	USES_ERROR_HANDLING;
	THROW_ON_FAILURE(m_wpWriter->CloseScope()); 
}


void	PersistenceWriter::StartCollection(PersistItemTag tag, System::UInt32 count)
{
	USES_ERROR_HANDLING;
	ULONG ulCount = count;
	THROW_ON_FAILURE(m_wpWriter->StartCollection(P2ETag(tag), ulCount)); 
}
void	PersistenceWriter::EndCollection()
{
	USES_ERROR_HANDLING;
	THROW_ON_FAILURE(m_wpWriter->EndCollection()); 
}

void	PersistenceWriter::SetValue( System::Boolean val)
{
	USES_ERROR_HANDLING;
	THROW_ON_FAILURE(m_wpWriter->SetBool(val ? TRUE : FALSE)); 
}
void	PersistenceWriter::SetValue( System::Double  val)
{
	USES_ERROR_HANDLING;
	THROW_ON_FAILURE(m_wpWriter->SetDouble((DOUBLE)val)); 
}
void	PersistenceWriter::SetValue( System::Int16  val)
{
	USES_ERROR_HANDLING;
	THROW_ON_FAILURE(m_wpWriter->SetShort((short)val)); 
}
void	PersistenceWriter::SetValue( System::Int32  val)
{
	USES_ERROR_HANDLING;
	THROW_ON_FAILURE(m_wpWriter->SetLong((long)val)); 
}
void	PersistenceWriter::SetValue( System::UInt32  val)
{
	USES_ERROR_HANDLING;
	THROW_ON_FAILURE(m_wpWriter->SetULong((ULONG)val)); 
}

void	PersistenceWriter::SetValue( System::String  ^  val)
{
	USES_ERROR_HANDLING;

    //pin_ptr<const wchar_t> pinchars = PtrToStringChars(val); 
	BSTR bstrTmp = (BSTR)(void*)System::Runtime::InteropServices::Marshal::StringToBSTR( val );
	THROW_ON_FAILURE( m_wpWriter->SetString( (WCHAR*)bstrTmp ) );
	System::Runtime::InteropServices::Marshal::FreeBSTR( (IntPtr)(void*)bstrTmp );
}

/*void	PersistenceWriter::SetValue( System::Object __gc *  val)
{
	USES_ERROR_HANDLING;

	VARIANT var;
	::VariantInit(&var);
	
	System::IntPtr wrappedPVar = (System::IntPtr)&var;
	System::Runtime::InteropServices::Marshal::GetNativeVariantForObject( val, wrappedPVar);

	CURRENT_STATUS = m_wpWriter->SetVariant(&var);
	::VariantClear(&var);

	THROW_ON_FAILURE(CURRENT_STATUS);

}*/

void	PersistenceWriter::SetValue( System::DateTime  val)
{
	USES_ERROR_HANDLING;
	__int64	ticks = val.Ticks;
	THROW_ON_FAILURE(m_wpWriter->SetDate(*(double*)&ticks)); 
}

void	PersistenceWriter::SetAttribute( PersistItemTag tag, System::Boolean val)
{
	USES_ERROR_HANDLING;
	THROW_ON_FAILURE(m_wpWriter->SetBoolAttribute(P2ETag(tag), val ? TRUE : FALSE)); 
}
void	PersistenceWriter::SetAttribute( PersistItemTag tag, System::Double  val)
{
	USES_ERROR_HANDLING;
	THROW_ON_FAILURE(m_wpWriter->SetDoubleAttribute(P2ETag(tag), (DOUBLE)val )); 
}
void	PersistenceWriter::SetAttribute( PersistItemTag tag, System::Int16  val)
{
	USES_ERROR_HANDLING;
	THROW_ON_FAILURE(m_wpWriter->SetShortAttribute(P2ETag(tag), (short)val )); 
}
void	PersistenceWriter::SetAttribute( PersistItemTag tag, System::Int32  val)
{
	USES_ERROR_HANDLING;
	THROW_ON_FAILURE(m_wpWriter->SetLongAttribute(P2ETag(tag), (long)val )); 
}
void	PersistenceWriter::SetAttribute( PersistItemTag tag, System::UInt32  val)
{
	USES_ERROR_HANDLING;
	THROW_ON_FAILURE(m_wpWriter->SetULongAttribute(P2ETag(tag), (ULONG)val )); 
}
void	PersistenceWriter::SetAttribute( PersistItemTag tag, System::String  ^  val)
{
	USES_ERROR_HANDLING;

	BSTR bstrTmp = (BSTR)(void*)System::Runtime::InteropServices::Marshal::StringToBSTR( val );
	THROW_ON_FAILURE( m_wpWriter->SetStringAttribute( P2ETag(tag), (WCHAR*)bstrTmp) );
	System::Runtime::InteropServices::Marshal::FreeBSTR( (IntPtr)(void*)bstrTmp );

}
/*void	PersistenceWriter::SetAttribute( PersistItemTag tag, System::Object __gc *  val)
{
	USES_ERROR_HANDLING;

	VARIANT var;
	::VariantInit(&var);
	
	System::IntPtr wrappedPVar = (System::IntPtr)&var;
	System::Runtime::InteropServices::Marshal::GetNativeVariantForObject( val, wrappedPVar);

	CURRENT_STATUS = m_wpWriter->SetVariantAttribute(P2ETag(tag), &var);
	::VariantClear(&var);

	THROW_ON_FAILURE(CURRENT_STATUS);

}*/
void	PersistenceWriter::SetAttribute( PersistItemTag tag, System::DateTime   val)
{
	USES_ERROR_HANDLING;
	__int64 ticks = val.Ticks;
	THROW_ON_FAILURE(m_wpWriter->SetDateAttribute(P2ETag(tag), *(double*)&ticks )); 
}
